package com.atguigu.test.processor;

import com.atguigu.test.config.SpringConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.*;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * @author zp
 * @version 1.0
 * @description: 自定义解析ConfigurationProcessor
 * @date 2022/12/16 19:15
 */
@Slf4j
public class MyConfigurationProcessor {
    public static void main(String[] args) throws IOException {
        GenericApplicationContext context = new GenericApplicationContext();

        context.registerBean("springConfig", SpringConfig.class);
        //context.registerBean(ConfigurationClassPostProcessor.class);

        //自定义ConfigurationClassPostProcessor
        ComponentScan annotation = AnnotationUtils.findAnnotation(SpringConfig.class, ComponentScan.class);
        if (annotation != null) {
            String[] strings = annotation.basePackages();
            // 获取解析class原数据的工厂类
            CachingMetadataReaderFactory readerFactory = new CachingMetadataReaderFactory();
            DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
            AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
            // 获取需要扫描的类
            for (String string : strings) {
                // 需要拼接的字符串classpath*:com/atguigu/test.po/**/*.class
                log.info("原先的字符串：[{}]", string);
                String path = "classpath*:" + string.replace(".", "/") + "/**/*.class";
                log.info("修改后的字符串：[{}]", path);
                Resource[] resources = context.getResources(path);
                for (Resource resource : resources) {
                    //log.info("扫描的资源：[{}]",resource);
                    MetadataReader metadataReader = readerFactory.getMetadataReader(resource);
                    // 获取类上面 注解的原数据
                    AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
                    // 检查这个注解和相关的派生注解
                    if (annotationMetadata.hasAnnotation(Component.class.getName()) || annotationMetadata.hasMetaAnnotation(Component.class.getName())) {
                        // 获取类的定义信息
                        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName()).getBeanDefinition();
                        // 生成beanName
                        String newName = generator.generateBeanName(beanDefinition, beanFactory);
                        // 根据bean信息定义生成新的bean信息
                        beanFactory.registerBeanDefinition(newName,beanDefinition);
                    }
                }
            }
        }
        context.refresh();

        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            log.info(beanDefinitionName);
        }

        context.close();
    }
}
